package com.yand.thinkingInJava.thinkingInJava21.threadNewcomponent;


import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

class DelayedTask implements Runnable, Delayed{

    private static int counter = 0;
    private int id = counter ++;
    private int delta;
    private long trigger;

    protected  static List<DelayedTask> sequence = new ArrayList<>();

    public DelayedTask(int delayInMilliseconds){
        delta = delayInMilliseconds;
        trigger = System.nanoTime() + TimeUnit.NANOSECONDS.convert(delta, TimeUnit.MILLISECONDS);

        sequence.add(this);
    }

    public long getDelay(TimeUnit unit){
        return unit.convert(trigger - System.nanoTime(),TimeUnit.NANOSECONDS);
    }



    @Override
    public int compareTo(Delayed o) {
        DelayedTask that = (DelayedTask)o;
        if(trigger < that.trigger){
            return -1;
        }
        if(trigger > that.trigger){
            return 1;
        }

        return 0;
    }

    @Override
    public void run() {
      System.out.println(this + " ");
    }

    public String toString(){
        return String.format("[%1$-4d]", delta)+ "Task "+id;
    }

    public String summary(){
        return "("+id+":"+delta+")";
    }

    public static class EndSentinel extends DelayedTask{

        private ExecutorService exec;
        public EndSentinel(int delayInMilliseconds,ExecutorService e) {
            super(delayInMilliseconds);
            exec = e;
        }

        public void run(){
            for(DelayedTask pt : sequence){
               System.out.println(pt.summary()+" ");
            }
            System.out.println(this + "Calling shutdownNew()");
            exec.shutdownNow();
        }

    }


}

class DelayedTaskConsumer implements Runnable{

    private DelayQueue<DelayedTask> q;

    public DelayedTaskConsumer(DelayQueue<DelayedTask> q){
        this.q = q;
    }

    @Override
    public void run() {
        try{
            while(!Thread.interrupted()){
                q.take().run();
            }

        }catch(InterruptedException e){

        }

        System.out.println("Finished DelayedTaskConsumer");
    }
}



/**
 * 延迟到期队列，队头元素，如果有到期的元素，取出，如果无则等待。。。
 */
public class DelayQueueDemo {

    public static void main(String [] args){
        Random rand = new Random(47);
        ExecutorService exec = Executors.newCachedThreadPool();
        DelayQueue<DelayedTask> queue = new DelayQueue<>();
        for(int i = 0 ; i < 20; i ++){
            queue.put(new DelayedTask(rand.nextInt(5000)));
        }
        queue.add(new DelayedTask.EndSentinel(5000,exec));
        exec.execute(new DelayedTaskConsumer(queue));
    }

}
